package org.bulldog.playlist.program;

import org.bulldog.playlist.PlayListener;
import org.bulldog.playlist.notice.NoticePlayList;
import org.bulldog.playlist.util.DateUtil;
import org.bulldog.playlist.util.ThreadUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by zhanghongbin on 2017/9/14.
 * 节目播表
 *
 * @author zhanghongbin
 * @version 1.0
 */
public final class ProgramPlayList {

    private static List<Program> playList;  //播表

    private static int playIndex = 0;//播放索引

    private static boolean rotationFlag = true;

    static {
        playList = new ArrayList();
    }

    private ProgramPlayList() {
    }

    public static boolean isEmpty() {
        return playList.isEmpty();
    }

    /**
     * 获取播放索引
     *
     * @return
     */
    public static int getPlayIndex() {
        return playIndex;
    }

    /**
     * 获取播表
     *
     * @return
     */
    public static List<Program> getPlayList() {
        return Collections.synchronizedList(playList);
    }

    /**
     * 生成播表
     *
     * @param dailyProgramList        排序好的日常节目
     * @param sportsProgramList       排序好的插播节目
     * @param sportsDailyProgramArray 排序好的插播日常节目
     * @param playListener            播放监听器
     */
    public static void build(List<Program> dailyProgramList, List<Program> sportsProgramList, List<Program>[] sportsDailyProgramArray, PlayListener playListener) {
        synchronized (ProgramPlayList.class) {
            playList.clear();
            playIndex = 0;
            //构建插播节目
            List<Program> sportsList = new SpotsCompositePlayListBuilder(sportsDailyProgramArray).build(sportsProgramList);
            //把插播节目先放到播放列表中，在获取普通节目有可能在容器里sportsList删除插播节目
            playList.addAll(sportsList);
            List<Program> dailyList = new DailyPlayListBuilder(sportsList).build(dailyProgramList);
            playList.addAll(dailyList);
            //播表排序
            Collections.sort(playList, ProgramAscendingOrder.ASCENDING_ORDER);
            dailyList.clear();
            sportsList.clear();
            sportsProgramList.clear();
            dailyProgramList.clear();
            try {
                playListener.onPlayListBuildFinish(PlayListener.Type.PROGRAM, playList);
            } catch (Exception e) {
                e.printStackTrace();
            }
            ProgramPlayList.class.notifyAll();
        }
    }

    /**
     * 执行播表
     *
     * @param playListener 播放监听器
     */
    public static void run(PlayListener playListener) {
        while (rotationFlag) {
            if (playList.size() > playIndex) {
                _run(playListener);
            } else {
                await();
            }
        }
    }

    private static void await() {
        synchronized (ProgramPlayList.class) {
            try {
                ProgramPlayList.class.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 播表轮播
     */
    private static void _run(final PlayListener playListener) {
        synchronized (ProgramPlayList.class) {
            if (playList.size() <= playIndex) return;
            final Program program = playList.get(playIndex);
            ThreadUtil.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        playListener.onPlay(PlayListener.Type.PROGRAM, program);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    NoticePlayList.backroll();//如果节目进行切换，需要查看有没有通知，如果有需要发送通知
                }
            });
            playIndex = playIndex + 1;
            try {
                ProgramPlayList.class.wait(program.getPlayDuration() * 1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 暂停
     */
    public static void pause() {
        synchronized (ProgramPlayList.class) {
            playIndex = Integer.MAX_VALUE;
            ProgramPlayList.class.notifyAll();
        }
    }


    /**
     * 运行默认节目
     *
     * @param playListener
     */
    private static void playDefaultProgram(final PlayListener playListener) {
        ThreadUtil.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    playListener.onPlay(PlayListener.Type.PROGRAM, new Program("-1", "", "", "", ""));
                } catch (Exception e) {
                }
                NoticePlayList.backroll();//如果节目进行切换，需要查看有没有通知，如果有需要发送通知
            }
        });
    }


    /**
     * 恢复节目播表执行
     */
    public static void recover(final PlayListener playListener) {
        synchronized (ProgramPlayList.class) {
            if (playList.isEmpty()) {
                //如果节目列表为空，则播放默认节目
                playDefaultProgram(playListener);
                return;
            }
            if (playIndex != Integer.MAX_VALUE) return;
            String currentDate = DateUtil.now();
            Program program = new Program();
            program.setStartTime(currentDate);
            int n = playList.indexOf(program);
            //如果没有找到，则从头开始播放
            if (n == -1) {
                playIndex = 0;
            } else {
                program = playList.get(n);
                //计算当前时间和结束时间的差值
                int value = DateUtil.minus(currentDate, program.getEndTime());
                //如果差值大于 10秒则播放在当前时间范围内的节目,小于10秒播放没有意义时间太短
                if (value >= 10) {
                    program.setDemandEndTime(currentDate);
                    program.setPlayDuration(value);
                    playIndex = n;
                } else {
                    if (value - 1 > 0) {
                        try {
                            Thread.sleep(1000 * (value - 1));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    //如果要播放的下一个节目已经超过了播表数量，则从头开始播放
                    playIndex = n + 1 >= playList.size() ? 0 : n + 1;
                }
            }
            ProgramPlayList.class.notifyAll();
        }
    }
}
